﻿

using InfluxDB.Client.Api.Domain;
using IoTClient;
using IotClientService.Models.Lg;
using IotClientService.Models.Lg.Remote;
using IotClientService.Services;
using IotContract.Enums;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Channels;
using System.Threading.Tasks;
using XT.Common.Extensions;

namespace IotClientService.Handles.lgs;
/// <summary>
/// 充放电处理程序,预充，补电
/// 2分钟周期fms发送909获取设备状态
/// 设备状态变更发送913报告，回914
/// 作业Mode变更，设备发送917，回918
/// Tray Load，设备发933，回934
/// Tray Unload，设备发937，回938
/// 设备Recipe(配方)邀请，设备发101，回102
/// 应答和结束，设备发905，回906
/// 指示设备把作业中的Sample Data报告，fms发929，设备回930
/// 作业完成后报告数据，设备发901，回902
/// 
/// 设备发送的size不对，相互发送981，ret=2
/// 发送的checksum不对，相互发送981，ret=3
/// 
/// 主动要求设备作业停止，fms发129，设备回130
/// 
/// 主动要作业再开始，fms发133，设备回134
/// 
/// 设备channel作业与否，设备发140,回141
/// 
/// FMS测定作业->trayload933(R),h934->trayload933(A),h934->recipe(配方）101,h102->channel作业与否140,h141
/// ->状态变更913->开始作业905,906->作业完成报告数据901,h902->作业完成905,h906->状态变更913
/// ->trayunload937(R),h938->trayunload937(E),h938
/// 
/// </summary>
public class LgHandleFmt : LgHandleBase
{
    public LgHandleFmt(ILgApiService lgCallApiService) : base(lgCallApiService)
    {
    }

    public override IotEquipType EquipType { get; set; } = IotEquipType.FMT;
    /// <summary>
    /// 处理消息
    /// </summary>
    /// <param name="msg"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public override async Task<bool> HandleMsg(LgMsgInfo msg)
    {
         string replyCmd = string.Empty;
        switch (msg.Command)
        {
            // 作业实处理Data报告
            case "901":
                replyCmd = "902";
               
                  await  Handle901(msg, replyCmd);
                
               
               
                break;
            // 作业开始/结束报告
            case "905":
                replyCmd = "906";
               await Handle905(msg, replyCmd);
                break;
            // 设备状态报告指示回应
            case "910":
               await Handle910(msg, "910");
                // send 833 

                break;
            // 设备状态报告
            case "913":
               await Handle913(msg, "913");

                break;
            // 作业mode报告
            case "917":
                replyCmd = "918";
               await Handle917(msg, replyCmd);
                break;
          
            // 通信状态报告邀请
            case "925":
                replyCmd = "926";
               await Handle925(msg, replyCmd);
                break;
            // 通信状态报告回应
            case "926":
               await Handle926(msg, "926");
                break;
            // Tray Load报告
            case "933":
                replyCmd = "934";
               await Handle933(msg, replyCmd);
                break;
            // Tray UnLoad报告
            case "937":
                replyCmd = "938";
               await Handle937(msg, replyCmd);
                break;
            // 未知命令,错误
            case "981":
               await Handle981(msg, "981");
                break;
            // 设备Trouble报告
            case "985":
               await Handle985(msg, "985");
                break;
            // Pin Error
            case "989":
               await Handle989(msg, "989");
                break;
            // tray Unload报告
            case "101":
                replyCmd = "102";
               await Handle101(msg, replyCmd);
                break;
            // 设备作业停止应答
            case "130":
               await Handle130(msg, "130");
                break;
            // 设备再作业应答
            case "134":
               await Handle134(msg, "134");
                break;
            // 最后状态报告
            case "136":
               await Handle136(msg,"136");
                break;
            // channel作业是否邀请
            case "140":
                replyCmd = "141";
              await  Handle140(msg, replyCmd);
                break;
            // Change Box Obrder
            case "150":
                replyCmd = "151";
               await Handle150(msg,replyCmd);
                break;
            case "152":
                replyCmd = "152";
                await Handle152(msg, replyCmd);
                break;

            // 作业再开始 / Tray Unload 邀请 回应
            case "834":
               await Handle834(msg, replyCmd);
                break;
            // 设置时间指示
            case "999":
               await Handle999(msg, replyCmd);
                break;
            default:
                // send 981
               await Handle981(msg, "981");
                break;
        }
        Api.LogData("ReplyCommand", replyCmd);
        return true;
    }
    /// <summary>
    /// 作业实处理Data报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle901(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            
        };
        
        // 获取作业种类 opergroupid
        // 1:恒流充电CC  2:恒压充电  3:恒流恒压充电 4:放电 5:REST 6:恒流恒压放电
        string operGroupId = msg.Message.Substring(18, 1);
        // 托盘
        string tray = msg.Message.Substring(19, 10);
        // 电芯配方
        string cells = msg.Message.Substring(39, msg.Message.Length - 39 - 2);
        int ret = 0;
        try
        {
            // 计算获取电芯数据 132*48个
            var cellCount = (int)(cells.Length / 132);
            List<LgCellCharge> cellCharges = new List<LgCellCharge>();
            for (int i = 0; i < cellCount; i++)
            {
                var data = cells.Substring(i * 132, 132);
                if(data.Trim().Length == 0) continue;
                var cellCharge = new LgCellCharge
                {
                    Channel = i + 1,
                    CellType = data.Substring(0, 1),
                    Step = data.Substring(1, 2).To<int>(),
                    StartVol = data.Substring(3, 8).To<double>(),
                    EndVol = data.Substring(11, 8).To<double>(),
                    StartElec = data.Substring(19, 10).To<double>(),
                    EndElec = data.Substring(29, 10).To<double>(),
                    StartCap = data.Substring(39, 9).To<double>(),
                    EndCap = data.Substring(48, 9).To<double>(),
                    StartEnergy = data.Substring(57, 9).To<double>(),
                    EndEnergy = data.Substring(66, 9).To<double>(),
                    AvgVol = data.Substring(75, 8).To<double>(),
                    DisChargeTime = data.Substring(83, 5).To<double>(),
                    ChargeTime = data.Substring(88, 5).To<double>(),
                    ProcessMaxTemp = data.Substring(93, 5).To<double>(),
                    ProcessMinTemp = data.Substring(98, 5).To<double>(),
                    ProcessAvgTemp = data.Substring(103, 5).To<double>(),
                    StartTemp = data.Substring(108, 5).To<double>(),
                    EndTemp = data.Substring(113, 5).To<double>(),
                    NtPressure = data.Substring(118, 3).To<double>(),
                    DcirValue = data.Substring(121, 7).To<double>(),
                    ErrorCode = data.Substring(128, 4)
                };
                cellCharges.Add(cellCharge);
            }
            var result = await Api.CommitFmtResult(new Models.Lg.Remote.LgFmtResultRequest
            {
                EquipNum=Equip.Num,
                OperGroupID = operGroupId.To<int>(),
                Tray = tray,
                CellCharges = cellCharges,
                EquipType = this.EquipType,
                ProgramType = Equip.ProgramType,
            });
            if (!result.Success)
            {
                Equip.ExMessage = result.Message;
                ret = 1;
            }
            else
            {
                ret = result.Result?.Ret ?? 1;
            }

        }
        catch(Exception ex)
        {
            Equip.Remark = ex.Message;
            ret = 1;
        }
        if (ret == 1)
        {
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }
        sendMsg.Body = ret.ToString() ;
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);


    }

   

    /// <summary>
    /// 作业开始/结束报告  多数据
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle905(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId=1
        };
        // 获取作业种类 opergroupid
        // 1: 恒流充电(CC)，2: 恒压充电(CV)，3 : 恒流恒压充电(CCCV) 4: 放电，5: REST 6：恒流恒压放电（CCDV）
        string operGroupId = msg.Message.Substring(18, 1);
        // 托盘
        string tray = msg.Message.Substring(19, 10);

        // S:应答  E:作业结束
        string status = msg.Message.Substring(39, 1);
        //温度数据
        string temperatures = msg.Message.Substring(40, 192);
        Equip.ExplainData = status;
        List<float> tempData = new List<float>();
        
        if (status == "S")
        {
            Equip.Obj = tray;
             
        }
        else if (status == "E") 
        {
            Equip.Obj = "";
            //处理温度
            for (int i = 0;i < (192 / 4); i++)
            {
                tempData.Add(temperatures.Substring(i * 4, 4).To<float>());
            }
        }
        int ret = 0;
        var result= await Api.CommitFmtReport(new Models.Lg.Remote.LgFmtReportRequest
        {
            EquipNum=Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType,
            OperGroupID=operGroupId.To<int>(),
            Tray=tray,
            Status=status,
            Temperatures = tempData
        });
        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            ret = 1;
        }
        else
        {
            ret = result.Result?.Ret ?? 1;
        }
        if (ret == 1)
        {
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }

        sendMsg.Body = $"{ret}{status}";
        sendMsg.IsSend = true;
      
        InvokeSend(sendMsg);

    }
    /// <summary>
    /// 设备状态报告指示回应 大量温度数据,需要获取
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle910(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId=1
        };

        // 设备状态 R:Running  I:Idle  T:Trouble  P:Power on  O:Power off
        string status = msg.Message.Substring(18, 1);
        // 作业模式 0:Control Model  1:Maintenance Mode
        string mode = msg.Message.Substring(19, 1);

        // 托盘有无  0:无  1:有
        string isExist = msg.Message.Substring(20, 1);

       
        // 烟雾感应  0:off  1:on
        string isWarn=msg.Message.Substring(21, 1);

        string cylinder = msg.Message.Substring(22, 1);

        //设备Channel 数 0: 16 1: 48
        string channelCount = msg.Message.Substring(23, 1);
        //73个温度 JIG部4个，通道部48个，电源部12个，JIG部 平均值、最小值、最大值，通道部 平均值、最小值、最大值，电源部 平均值、最小值、最大值
        string temperatures = msg.Message.Substring(24, 73 * 4);
        List<float> tempData = new List<float>();
        for (int i = 0; i < (192 / 4); i++)
        {
            tempData.Add(temperatures.Substring(i * 4, 4).To<float>());
        }
        Equip.EquipStatus = status;
        Equip.Mode = mode;

        var result = await Api.CommitFmtEquipStatus(new Models.Lg.Remote.LgFmtEquipStatusRequest
        {
            EquipNum = Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType,
            ExistTray = isExist.To<int>(),
            Mode = mode.To<int>(),
            Status = status.To<int>(),
            Cylinder = cylinder.To<int>(),
            channelCount = channelCount.To<int>(),
            SmokeSensor = isWarn.To<int>(),
            Temperatures = tempData
        });
        int ret = 0;
        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            ret = 1;
        }
        else
        {
            ret = result.Result?.Ret ?? 1;
        }
        if (ret == 1)
        {
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }

        InvokeSend(sendMsg);
    }
   
   
    


    /// <summary>
    /// Tray Load报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    public virtual async Task Handle933(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        
        // A:Arrive R:Request
        var status = msg.Message.Substring(18, 1);
        Equip.ExplainData = status;
        Equip.Remark = $"Tray Load:{status}";

        // 0:ok 1:ng  
        int ret = 0;
        // 1:正常  2:空托盘
        var type = "1";
        var result= await Api.CommitFmtEnter(new Models.Lg.Remote.LgTrayReportRequest
        {
            EquipNum=Equip.Num,
            EquipType =this.EquipType,
            ProgramType = Equip.ProgramType,
            Status = status
        });

        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            ret = 1;
        }
        else
        {
            ret = result.Result?.Ret ?? 1;
            type = result.Result?.Type.ToString();
            if (status == "R")
            {
                type = "";
            }
        }
        if (ret == 1)
        {
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }
        #region 传输body

        var trayid = string.Empty;
        trayid = trayid.PadRight(20, ' ');
        if (result.Result.IsNotNull() && !string.IsNullOrEmpty(result.Result.Tray))
        {
            trayid = result.Result.Tray.PadRight(20, ' ');
        }
        else
        {
            trayid = trayid.PadRight(20, ' ');
        }
        
        Equip.Obj = trayid;

        var cellcount = "00";
        string cells = string.Empty;
        if (result.Result.Cells.IsNotNull())
        {
            cellcount = result.Result.Cells.Count.ToString().PadLeft(2, '0');
        }
        

        for (int i = 1; i <= 48; i++)
        {
            var cell = result.Result.Cells?.FirstOrDefault(x => x.channel == i);
            if (cell == null)
            {
                cells += "".PadRight(24, ' ');
            }
            else
            {
                cells += cell.cellCode.PadRight(24, '0');
            }
        }
        
        // M11__ 产品型号
        var model = ((result.Result?.Prod)??"").PadRight(10, ' ');


        #endregion
        sendMsg.Body = $"{ret}{trayid}{cellcount}{cells}{model}{type}";
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);
    }
    /// <summary>
    /// Tray UnLoad报告
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    public virtual async Task Handle937(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,

        };
        // 托盘
        var tray = msg.Message.Substring(18, 10);
        // E:End完成 R:Request(Unload邀请) O:Open Jig(化成用)
        var status = msg.Message.Substring(38, 1);

       
        Equip.Obj = "";
        Equip.ExplainData = status;
        // 0:ok 1:ng,再传送后trouble
        int ret = 0;
        var result = await Api.CommitFmtOut(new Models.Lg.Remote.LgTrayReportRequest
        {
            EquipNum = Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType,
            Tray = tray,
            Status = status
        }) ;
        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            ret = 1;
        }
        else
        {
            ret = result.Result?.Ret ?? 1;
        }
        if (ret == 1)
        {
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }
        Equip.Remark = $"tray unload:{tray}-{status}";
        
        sendMsg.Body = $"{ret}";
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);
    }


    /// <summary>
    /// Pin Error
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle989(LgMsgInfo msg,string replyCmd)
    {
        // 48可变，根据设备channel来
        string troubleIds = msg.Message.Substring(18, 48);
        StringBuilder errorPins = new StringBuilder();
        for (int i = 0; i < troubleIds.Length; i++)
        {
            if (troubleIds[i] == '1') 
            { 
                errorPins.Append((i + 1) + ",");
            }
        }
        if (errorPins.Length > 0)
        {
            Equip.Remark = "PinError:" + errorPins.ToString().Substring(0, errorPins.Length - 1);
        }
       
        InvokeSend(msg);
    }
    /// <summary>
    /// 进行recipe邀请
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle101(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 0,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId=1
        };
        var tray = msg.Message.Substring(18, 10);

        

        Equip.Obj = tray;
        Equip.Remark = $"tray:{tray}";


        var result=  await Api.GetFmtRecipe(new Models.Lg.Remote.LgTrayReportRequest
        {
            Tray = tray,
            EquipType = this.EquipType,
            EquipNum = Equip.Num,
            ProgramType = Equip.ProgramType
        });
        var recipeId = string.Empty;
        var stepNum = string.Empty;
        var stepStr = string.Empty;
        var fmtProtect = string.Empty;
        var channel = 1;
        var trayId = tray.PadRight(20, ' ');
        int ret = 0;
        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            msg.Body = ret.ToString();
            await Handle981(msg, "981");
            return;
        }
        else
        {
            recipeId = result.Result.RecipeID.PadLeft(10, '0');
            // total step (1-9)
            stepNum = result.Result.Steps.Count.ToString().PadLeft(2, '0');
            foreach (var step in result.Result.Steps)
            {
                stepStr += step.ToString();
            }
            // 保护数据
            fmtProtect = result.Result.Protect.ToString();
            // 0:24 channel   1:48 Channel
            channel = result.Result.ChannelCount;
            sendMsg.Body = $"{recipeId}{trayId}{channel}{stepNum}{stepStr}{fmtProtect}";
        }
       
        sendMsg.IsSend = true;
        InvokeSend(sendMsg);
    }
    /// <summary>
    /// 设备作业停止应答
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle130(LgMsgInfo msg,string replyCmd)
    {
        // 0:正常停止
        // 1:停止失败
        var ret = msg.Message.Substring(18, 1);
        Equip.Action = ret;
        Equip.Remark = $"Stop:{ret}";
        InvokeSend(msg);

    }
    /// <summary>
    /// 设备作业再开始指示应答
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle134(LgMsgInfo msg,string replyCmd)
    {
        // 0:正常 再开始
        // 1:在开始失败
        // 2:再开始失败（没有再作业的Tray）
        var ret = msg.Message.Substring(18, 1);
        Equip.Remark = $"ReStart:{ret}";

        Equip.Action = ret;
        InvokeSend(msg);
    }
    /// <summary>
    /// 最后状态报告指示应答
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle136(LgMsgInfo msg,string replyCmd)
    {
        // 最后设备传送的CommandID
        var lastCommand = msg.Message.Substring(18, 3);
        // 1: 恒流充电(CC)，2: 恒压充电(CV)，3 : 恒流恒压充电(CCCV) 4: 放电，5: REST 6：恒流恒压放电（CCDV）
        var operGroupId = msg.Message.Substring(21, 1);
        // routeid+recipe id
        var recipeId = msg.Message.Substring(22, 10);

        Equip.Remark = $"LastCommand:{lastCommand} opera:{operGroupId}";
        InvokeSend(msg) ;
    }
    /// <summary>
    /// Channel作业是否邀请
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle140(LgMsgInfo msg, string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 1,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId = 1,
            IsSend = true

        };
        var tray = msg.Message.Substring(18, 10);

        
        Equip.Obj = tray;

       var result= await Api.GetFmtChannel(new Models.Lg.Remote.LgTrayReportRequest
        {
            Tray = tray,
            EquipNum = Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType
        });
        // 0:作业  1:作业禁止
        var channels = "1".PadRight(48, '1');
        if (!result.Success)
        {
            Equip.ExMessage = result.Message;
            msg.Body = "1";
            await Handle981(msg, "981");
            return;
        }
        else
        {
            channels = result.Result.Channel.PadRight(48, '1');
        }
       
        var trayid = tray.PadRight(20, ' ');

        sendMsg.Body = $"{trayid}{channels}";
        sendMsg.IsSend = true;
       
        InvokeSend(sendMsg);
    }
    /// <summary>
    /// Change Box Order,换库申请
    /// </summary>
    /// <param name="msgInfo"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle150(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 1,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId = 1,
            IsSend = true

        };
        var result= await Api.CommitFmtChangeBox(new Models.Lg.Remote.LgRequestBase
        {
            EquipNum = Equip.Num,
            EquipType = this.EquipType,
            ProgramType = Equip.ProgramType
        });
        sendMsg.Body = (result.Result?.Ret??1).ToString();
        InvokeSend(msg);
    }
    /// <summary>
    /// Calibration Box Move
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle152(LgMsgInfo msg,string replyCmd)
    {
        var sendMsg = new LgMsgInfo
        {
            Direction = 0,
            ObjID = msg.ObjID,
            HasMsg = 1,
            SeqNo = msg.SeqNo,
            Command = replyCmd,
            BoxId = 1,
            IsSend = true

        };

        var fromUnit = msg.Message.Substring(18, 5);
       
        var toUnit = msg.Message.Substring(23, 5);
        // 1:出去  2:回来
        var type = msg.Message.Substring(28, 1);

        Equip.Remark = $"fromUnit:{fromUnit} toUnit:{toUnit} type:{type}";

        InvokeSend(sendMsg);
    }
    
    /// <summary>
    /// 作业再开始指示回应
    /// </summary>
    /// <param name="msg"></param>
    /// <param name="replyCmd"></param>
    private async Task Handle834(LgMsgInfo msg, string replyCmd)
    {
        // 0:正常再开始 1:再开始 失败（机械性Trouble） 2:在开始失败（没有作业的Tray）
        string ret = msg.Message.Substring(18, 1);

        Equip.Action = ret;

        Equip.Remark = $"again:{ret}";
        InvokeSend(msg);
    }



}
